我們前面做好 註冊/登入 系統了,那當然要來測試一下,限制一些頁面只有登入以後才能進入拉~
登入權限的設定有分兩種,一種是我們在 views.py 自訂的 基礎函式,像是我們首頁 def index,另一種就是我們使用 Django 提供的版本,像是我們老闆列表頁 EmployerListView,這兩種限制登入權限瀏覽的設定是不一樣的
首先我們看一下 基礎函式 def index 的設定方式:
from django.contrib.auth.decorators import login_required
@login_required
def index(request):
# ...省略
這邊說明一下上面在幹嘛,@login_required 是一個 Django 裝飾器(decorator),裝飾器用於修改或擴展 views 的行為。今天這樣設定,@login_required 裝飾器用於限制訪問特定 views 的使用者必須處於已登入狀態,否則他們將被重導到登入頁面。
白話文就是,當我今天在 index 上方加上 @login_required,之後你進到對應的網址,也就是 http://127.0.0.1:8000/online/,他會因為你設定登入權限的關係,自動轉跳到 http://127.0.0.1:8000/accounts/login/?next=/online/ 登入頁面

那如果今天是這一種 EmployerListView,是由 Django 提供的 模版函示 要怎麼設定呢?只要像這樣設定就好:
from django.contrib.auth.mixins import LoginRequiredMixin
class EmployerListView(LoginRequiredMixin, generic.ListView):
model = Employer
這個模板權限設定的效果跟 @login_required ˊ一樣,只要這樣設定後,當你進入 http://127.0.0.1:8000/online/employers/,他就會自動轉跳到 http://127.0.0.1:8000/accounts/login/?next=/online/employers/ 登入頁面

如果今天想要客製化一種驗證,也可以做到,首先我們先看一下這一張圖:

這個畫面是 admin 後台的調整使用者權限的地方,目前可以看到 Store 的權限有四個 add、change、delete、view,就是基本的 CRUD,我們現在來針對 Store 增加一種權限
我們在 model 的 Store 地方加上 Meta permissions,我們用 tuple 包住他們,左邊是驗證的名稱,右邊是驗證的值(聽不懂沒關係,等等會實作)
# store/online/models.py
class Store(models.Model):
# ...省略
class Meta:
permissions = (("can_mark_store", "Set store as noticed"),)
這邊調整完後,記得具現化表單
$ python3 manage.py makemigrations
------
Migrations for 'online':
online/migrations/0004_alter_store_options.py
- Change Meta options on store
$ python3 manage.py migrate
------
Operations to perform:
Apply all migrations: admin, auth, contenttypes, online, sessions
Running migrations:
Applying online.0004_alter_store_options... OK
具現化好後,我們再打開 admin 的後台,到調整使用者權限的地方看,應該會如下圖:

會發現多了一個 Set store as noticed 的權限設定,而這個名字就是我們剛剛在 Meta permissions 中增加的值
新增好值後,接著我們到 views 的地方來設定是否可以瀏覽特定頁面
# online/views.py
from django.contrib.auth.mixins import PermissionRequiredMixin
class StoreListView(PermissionRequiredMixin, generic.ListView):
model = Store
permission_required = 'online.can_mark_store'
raise_exception = True # 如果用戶沒有權限,引發PermissionDenied異常
我們在 StoreListView 這個 Django 客製化的 listView 修改成這樣,解釋一下上面在幹嘛:
PermissionRequiredMixin這個東西是使用客製化權限設定時候用的的參數StoreListView 引入該參數,permission_required後面的字串是 應用程式.客製權限名稱,因此是 online.can_mark_store,can_mark_store 這個就是我們在 Meta permissions 中新增的名稱最後就是在 StoreListView 對應的連結 http://127.0.0.1:8000/online/stores/ 測試驗證結果拉 :
<!-- store/online/templates/online/store_list.html -->
{% extends 'sidebar.html' %}
{% block content %}
{% if perms.online.can_mark_store %}
<p>你有權限的話看得到我</p>
{% endif %}
<!-- ...省略 -->
{% endblock %}
可以看到下圖,因為我這個帳號是最高權限,所以基本上所有訊息都看得到:

在Django中,perms(也稱為權限)是一種機制,用於控制哪些使用者(user)或群組(group)可以執行特定操作或訪問特定資源。Django的權限系統允許你精細地控制你的應用程式中的瀏覽權限:
如果不懂的話,我們直接把 perms 印出來看,你就知道了:
<!-- store/online/templates/online/store_list.html -->
{% extends 'sidebar.html' %}
{% block content %}
<!-- ...省略 -->
{{ perms }}
<br>
{{ perms.online }}
<!-- ...省略 -->
{% endblock %}
可以發現我們印出來,他會顯示你現在的帳號有哪些權限,可以依照擁有的權限來做特定的事情

剛剛上面如果聽不懂的話,可以直接來看應用方式,由於剛剛因為是超級使用者,所以他可以進入所有頁面、看到所有的文字,那我們現在改成,一個使用者有瀏覽 store-list 也就是瀏覽 http://127.0.0.1:8000/online/stores/ 連結的權限,但是沒有 can_mark_store 的權限,因此這個使用者進到 http://127.0.0.1:8000/online/stores/ 頁面後,看不到 你有權限的話看得到我 這一段字。
首先把 StoreListView 這個 class 的權限改成要有 view_store 權限才能進入
class StoreListView(PermissionRequiredMixin, generic.ListView):
model = Store
permission_required = ('online.view_store')
raise_exception = True # 如果用戶沒有權限,引發PermissionDenied異常
接著我們開一個新的使用者,此使用者沒有最高權限,我們實際測試使用者名稱為 - test1234 的使用者,我們把他的權限增加 online | store | Can view store,如下圖:

接著來看我們的 templates 頁面,不過其實不用修改,因為我們前面已經加上條件限制 if perms.online.can_mark_store,要有 mark_store 的權限才能看到這一行字,因此你看到的圖會長這樣:

少了 你有權限的話看得到我 這一段字,並且 perms.online 印出的權限只有 {'online.view_store'},這樣看完之後應該就很清楚了!
這樣我們就詳細說明了 Django 的 登入 / 註冊 / 權限 要如何使用~
今天學到哪些東西呢?
最後附上 Github: https://github.com/eagle0526/Django-store